'''
Created on 15/02/2011

@author: Vinicius

Mapas auto-organizaveis
'''
from numpy.linalg.linalg import norm
from funcoes import valorMinimo
from math import exp
from numpy import matrix , min, ndarray
from numpy.random import randn
from numpy.matlib import zeros

#Executa a auto-organizacao ate a convergencia 
def execute(i,grade,decayAlfa,decayRate,alfa0,rate0,itrMax):
    
    n = 0
    global input,w,g,t1,t2,a0,n0
    g = grade 
    a0 = alfa0
    n0 = rate0
    t1 = decayAlfa
    t2 = decayRate
    input = i
    v = {}
  
    w = randn(g[0]*g[1],len(input[0]))
    while n < itrMax*g[0]*g[1]:
        for j in range(g[0]*g[1]):
            v[j] = []
        for k in range(len(input)):
            i = compute_indice(k)
            v[i].append(k)
            compute_weights(n, i, k)
        n+=1
    return (w,v,n)

'Eq. 9.3'
# Processo de competicao - neuronio vencedor
def compute_indice(k):
    res = []
    for j in range(len(w)):
        i = norm(input[k]-w[j],len(input[k]))
        res.append(i)
    return valorMinimo(res)

'Eq. 9.6'
# Taxa de depreciamento do espalhamento da vizinhanca
def alfa_decay(n):
    return a0*exp(-n/t1)

'Eq. 9.7'
# Processo de cooperacao - funcao de vizinhanca
def neighborhood_function(j,i,n):
    rj = matrix([j/g[1],j%g[1]])
    ri = matrix([i/g[1],i%g[1]])
    d2 = pow(norm(rj-ri, len(rj)),2)
    a = alfa_decay(n)
    return exp(-d2/2*pow(a,2))

'Eq. 9.14'
#Taxa de depreciamento da taxa de aprendizagem
def lRate_decay(n):
    return n0*exp(-n/t2) 

'Eq. 9.13'
# Processo de adaptacao - atualizacao dos pesos
def compute_weights(n,i,k):
    for j in range(len(w)):
        l = lRate_decay(n)
        h = neighborhood_function(j,i,n)
        d = input[k]
        e = w[j]
        c =  d - e 
        w[j] = w[j]+ l*h*c